﻿using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Casamiel.API.Infrastructure.Middlewares
{

    /// <summary>
    /// Token实体
    /// </summary>
    public class TokenEntity
    {
        /// <summary>
        /// token字符串
        /// </summary>
        public string access_token { get; set; }
        /// <summary>
        /// 过期时差
        /// </summary>
        public long expires_in { get; set; }
    }
    /// <summary>
    /// Token provider.
    /// </summary>
	public interface ITokenProvider
    {
        /// <summary>
        /// Generates the token.
        /// </summary>
        /// <returns>The token.</returns>
        /// <param name="mobile">Mobile.</param>
		TokenEntity GenerateToken(string mobile);
    }
    /// <summary>
    /// Token provider.
    /// </summary>
    public class TokenProvider : ITokenProvider
    {
        readonly TokenProviderOptions _options;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tokenProviderOptions"></param>
        public TokenProvider(TokenProviderOptions tokenProviderOptions)
        {
            _options = tokenProviderOptions;
        }
        /// <summary>
        /// </summary>
		public TokenProvider()
        {
            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("cssupersecret_secretke!miel"));
            TokenProviderOptions _tokenOptions = new TokenProviderOptions
            {
                Audience = "casamiel",
                Issuer = "CasamielIssuer",
                SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
            };
            _options = _tokenOptions;
        }

        /// <summary>
        /// Generates the token.
        /// </summary>
        /// <returns>The token.</returns>
        /// <param name="mobile">Mobile.</param>
        public TokenEntity GenerateToken(string mobile)
        {
            string jti;
            string role = "";
            var handler = new JwtSecurityTokenHandler();
            var rsa = new RSAHelper(RSAType.RSA2, Encoding.UTF8, RSAHelper.privateKey, RSAHelper.publicKey);
            jti = mobile;
            jti = rsa.Encrypt(jti);//jti.GetMd5();
            var now = DateTime.UtcNow;
            //声明
            var claims = new Claim[]
            {
             new Claim(JwtRegisteredClaimNames.Sub,mobile),
             new Claim(JwtRegisteredClaimNames.Jti,jti),
             new Claim(JwtRegisteredClaimNames.Iat,ToUnixEpochDate(now).ToString(CultureInfo.CurrentCulture),ClaimValueTypes.Integer64),
             new Claim(ClaimTypes.Role,role),
             new Claim(ClaimTypes.Name,mobile)
            };
            //Jwt安全令牌
            var jwt = new JwtSecurityToken(
                issuer: _options.Issuer,
                audience: _options.Audience,
                claims: claims,
                notBefore: now,
                expires: now.Add(_options.Expiration),
                signingCredentials: _options.SigningCredentials);
            //生成令牌字符串
            var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
            var response = new TokenEntity
            {
                access_token = encodedJwt,
                expires_in = (int)_options.Expiration.TotalSeconds
            };
            return response;
        }

        private static long ToUnixEpochDate(DateTime date)
        {
            return (long)Math.Round((date.ToUniversalTime() - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)).TotalSeconds);
        }

    }
}
